from typing import List, Literal, Union

from mailmerge import MailMerge
from openpyxl import load_workbook
from openpyxl.styles import Alignment
from pydantic import BaseModel, Field

from src.config import Config
from src.models.mail import FormerGraduateRecord, FreshGraduateRecord


class YJTZTemplate(BaseModel):
    """应届通知模板"""

    student_id: str = Field(serialization_alias="学号")
    graduate_at: str = Field(serialization_alias="届别")
    name: str = Field(serialization_alias="姓名")
    send_time: str = Field(serialization_alias="寄出时间")
    archives_transfer_unit: str = Field(serialization_alias="档案转递单位名称")
    id_card_number: str = Field(serialization_alias="身份证号")
    archives_transfer_number: str = Field(serialization_alias="转递编号")
    origin_address: str = Field(serialization_alias="生源所在地")
    contact: str = Field(serialization_alias="联系方式")
    archive_transfer_type: str = Field(serialization_alias="档案转递类型")
    employer: str = Field(serialization_alias="单位名称")
    employer_address: str = Field(serialization_alias="单位地址")
    major: str = Field(serialization_alias="专业")

    @classmethod
    def from_fresh_graduate_record(cls, record: FreshGraduateRecord) -> "YJTZTemplate":
        return cls(
            student_id=record.id,
            graduate_at=record.graduate_at,
            name=record.name,
            send_time=record.send_time.strftime("%Y年%m月%d日"),
            archives_transfer_unit=record.archives_recv_unit_name,
            id_card_number=record.student_id_card_number,
            archives_transfer_number=record.archives_recv_number,
            origin_address=record.student_origin_address,
            contact=record.student_phone_number,
            archive_transfer_type=record.archives_recv_type,
            employer=record.employer,
            employer_address=record.employer_address,
            major=record.major,
        )


class WJTZTemplate(BaseModel):
    """应届通知模板"""

    name: str = Field(serialization_alias="姓名")
    major: str = Field(serialization_alias="专业")
    archive_receive_unit: str = Field(serialization_alias="档案接收单位、部门")
    archive_receive_address: str = Field(serialization_alias="档案接收地址")
    send_time: str = Field(serialization_alias="寄出时间")
    student_id: str = Field(serialization_alias="学号")

    @classmethod
    def from_former_graduate_record(
        cls, record: FormerGraduateRecord
    ) -> "WJTZTemplate":
        return cls(
            name=record.name,
            major=record.major,
            archive_receive_unit=record.archives_recv_unit_name,
            archive_receive_address=record.archives_recv_address,
            send_time=record.send_time.strftime("%Y年%m月%d日"),
            student_id=record.id,
        )


class DeliveryTemplate(BaseModel):
    """快递模板"""

    sender_name: str = Field(serialization_alias="寄件人姓名")
    sender_phone: str = Field(serialization_alias="寄件人手机")
    sender_fixed_phone: str = Field(default="", serialization_alias="寄件人固话")
    sender_address: str = Field(serialization_alias="寄件地址")
    recipient_name: str = Field(serialization_alias="收件人姓名")
    recipient_contact: str = Field(serialization_alias="收件人联系方式")
    recipient_address: str = Field(serialization_alias="收件地址")
    item_type: Literal["日用品", "食品", "文件", "衣物", "数码产品", "其他"] = Field(
        serialization_alias="物品类（在以下6类中选择：日用品、食品、文件、衣物、数码产品、其他）",
    )
    item_details: str = Field(default="", serialization_alias="物品详情")
    remark: str = Field(default="", serialization_alias="备注信息")

    @classmethod
    def from_config_and_record(
        cls,
        config: Config,
        record: Union[FreshGraduateRecord, FormerGraduateRecord],
        item_type: Literal[
            "日用品", "食品", "文件", "衣物", "数码产品", "其他"
        ] = "文件",
        item_details: str = "档案文件",
        remark: str = "",
    ) -> "DeliveryTemplate":
        return cls(
            sender_name=config.sender.name,
            sender_phone=config.sender.phone,
            sender_fixed_phone=config.sender.fixed_phone,
            sender_address=config.sender.address,
            recipient_name=record.archives_recvier,
            recipient_contact=record.archives_recvier_phone_number,
            recipient_address=record.archives_recv_address,
            item_type=item_type,
            item_details=item_details,
            remark=remark,
        )


def _mail_merge(template_docx_path: str, output_docx_path: str, data: dict):
    with MailMerge(template_docx_path) as doc:
        doc.merge(**data)
        doc.write(output_docx_path)


def yj_mail_merge(template_docx_path: str, output_docx_path: str, data: YJTZTemplate):
    """
    生成应届毕业生通知单
    :param template_docx_path: 模板文件路径
    :param output_docx_path: 输出文件路径
    :param data: 数据字典，键为表头，值为数据
    """
    _mail_merge(template_docx_path, output_docx_path, data.model_dump(by_alias=True))


def wj_mail_merge(template_docx_path: str, output_docx_path: str, data: WJTZTemplate):
    """
    生成非应届毕业生通知单
    :param template_docx_path: 模板文件路径
    :param output_docx_path: 输出文件路径
    :param data: 数据字典，键为表头，值为数据
    """
    _mail_merge(template_docx_path, output_docx_path, data.model_dump(by_alias=True))


def generate_kuaidi_xlsx(
    template_xlsx_path: str,
    output_xlsx_path: str,
    data: List[DeliveryTemplate],
):
    """
    生成快递模板Excel文件
    :param template_xlsx_path: 模板文件路径
    :param output_xlsx_path: 输出文件路径
    :param data: 数据字典，键为表头，值为数据
    """

    # 加载已有模板
    wb = load_workbook(template_xlsx_path)
    ws = wb.active
    if ws is None:
        raise ValueError("Excel文件中没有活动工作表")
    center_alignment = Alignment(horizontal="center", vertical="center")
    # 将data的values按顺序写入B-K列，从第三行开始
    for item_idx, item in enumerate(data, start=3):
        values = item.model_dump(by_alias=True).values()
        for col_idx, value in enumerate(values, start=2):
            cell = ws.cell(row=item_idx, column=col_idx, value=value)
            cell.alignment = center_alignment

    wb.save(output_xlsx_path)


if __name__ == "__main__":
    from datetime import datetime

    yj_docx = r"templates/1-通知单/应届毕业生通知单/本科生档案转递通知单—更新时间20230620.docx"
    wj_docx = (
        r"templates/1-通知单/非应届毕业生通知单/本科毕业生档案转递通知单-2024.docx"
    )
    wjtz = WJTZTemplate.from_former_graduate_record(
        FormerGraduateRecord(
            id="200110000",
            last_modified_time=datetime(2024, 6, 10),
            create_time=datetime(2024, 6, 10),
            name="张三",
            major="计算机科学与技术",
            send_time=datetime(2024, 6, 10),
            archives_recv_unit_name="重庆市永川区住房和城乡建设委员会",
            archives_recv_address="重庆市永川区重庆市永川区学府大道333号",
            archives_recvier="张三",
            archives_recvier_phone_number="13800000000",
            education_level="本科",
        )
    )
    wj_mail_merge(wj_docx, "output1.docx", wjtz)
    yjtz = YJTZTemplate.from_fresh_graduate_record(
        FreshGraduateRecord(
            name="张三",
            id="200110000",
            major="计算机科学与技术",
            graduate_at="2024届",
            send_time=datetime(2024, 6, 10),
            employer="重庆市永川区住房和城乡建设委员会",
            employer_address="重庆市永川区重庆市永川区学府大道333号",
            student_origin_address="重庆市永川区",
            student_id_card_number="44010119900101001X",
            student_phone_number="13800000000",
            archives_recv_type="档案转递",
            archives_recv_number="20240610001",
            archives_recv_unit_name="重庆市永川区住房和城乡建设委员会",
            archives_recv_address="重庆市永川区重庆市永川区学府大道333号",
            archives_recvier="张三",
            archives_recvier_phone_number="13800000000",
            education_level="本科",
            last_modified_time=datetime(2024, 6, 10),
            create_time=datetime(2024, 6, 10),
        )
    )
    yj_mail_merge(yj_docx, "output2.docx", yjtz)
    xlsx = r"templates/2-快递单/菜鸟发货平台专用导入模板（灵活寄件地址版，最多导入5000个）.xlsx"

    dt = DeliveryTemplate(
        sender_name="李老师",
        sender_phone="13800000000",
        sender_fixed_phone="",
        sender_address="重庆市永川区重庆市永川区学府大道333号",
        recipient_name="张三",
        recipient_contact="13800000000",
        recipient_address="重庆市永川区重庆市永川区学府大道333号",
        item_type="文件",
        item_details="100本《大学英语》",
        remark="",
    )
    generate_kuaidi_xlsx(xlsx, "kuaidi.xlsx", [dt])
